/* Copyright 2008 Bas van den Berg
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ELEVATORCONTROLLER_H
#define ELEVATORCONTROLLER_H

#include <map>
#include <deque>

#include "MudObject.h"

namespace Chronos {

class Room;
class MudExit;
class Area;
class MudPlayer;
class ElevatorControllerTask;


class ElevatorController {
public:
	ElevatorController(Room& elevator_, MudExit* toElevator_, Area& area_);
	~ElevatorController();
	void addFloor(int floorID, unsigned int roomID);
	unsigned int run();
	void request(MudPlayer& player, int floor);
private:
	void addRequest(int floor);
	int handleRequests();
	void reschedule(unsigned int delay_secs);
	unsigned int moveElevator();
	void openDoors();
	void closeDoors();

	const static unsigned int ELEVATOR_OPEN_TIME = 6;
	const static unsigned int ELEVATOR_MOVE_TIME = 5;

	struct Floor {
		unsigned int roomID;
		MudExit* fromElevator;
		Floor(unsigned int r, MudExit* from) : roomID(r), fromElevator(from) {}
	};
	typedef std::map<int, Floor*> Floors;
	typedef Floors::const_iterator FloorsConstIter;
	Floors floors;
	typedef std::deque<int> Requests;
	typedef Requests::iterator RequestsIter;
	Requests requests;
	MudExit* toElevator;

	int currentFloor;
	enum State {IDLE, DOORS_OPEN, MOVING} state;
	MudExit* elevatorEntry;
	Area& area;
	Room& elevator;
	ElevatorControllerTask* task;
};


class ElevatorButton : public MudObject {
public:
	ElevatorButton(const std::string& name_, ElevatorController& controller_, int floor_);
    virtual void accept(CmdVisitor& v);
	void push(MudPlayer& player);
private:
	ElevatorController& controller;
	int floor;
};

}

#endif

